package git.soulbgm.utils;

import git.soulbgm.common.pojo.BaseCallback;
import git.soulbgm.common.pojo.BaseModelCallback;
import git.soulbgm.pojo.Weather;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author SoulBGM
 * @version 1.0
 * @date 2019/7/4 13:45
 */
@Slf4j
public class OkHttpUtil {

    private static final Map<String, Object> PARAMS = null;

    /**
     * 将参数添加到RequestBody中
     *
     * @param params 参数
     * @return 添加好参数的RequestBody
     */
    public static RequestBody getRequestBody(Map<String, Object> params) {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null) {
            Set<String> keySet = params.keySet();
            for (String key : keySet) {
                Object obj = params.get(key);
                builder.add(key, String.valueOf(obj == null ? "" : obj));
            }
        }
        return builder.build();
    }

    /**
     * 仅限GET请求
     * 参数拼接
     *
     * @param params 参数
     * @return ?key=val&key=val 格式的字符串
     */
    public static String paramsJoin(Map<String, Object> params) {
        StringBuilder pathParams = new StringBuilder();
        if (params != null) {
            pathParams.append("?");
            Set<String> keySet = params.keySet();
            for (String key : keySet) {
                Object obj = params.get(key);
                pathParams.append(key);
                pathParams.append("=");
                pathParams.append(String.valueOf(obj == null ? "" : obj));
                pathParams.append("&");
            }
            pathParams.deleteCharAt(pathParams.length() - 1);
        }
        return pathParams.toString();
    }

    /**
     * 同步获取http访问结果
     *
     * @param call Call对象
     * @return http访问返回的结果
     */
    private static String getResult(Call call) {
        try {
            Response response = call.execute();
            ResponseBody body = response.body();
            byte[] bytes = body != null ? body.bytes() : new byte[0];
            return new String(bytes);
        } catch (IOException e) {
            log.error("请求{}出现异常", call.request().url().toString(), e);
            return null;
        }
    }

    /**
     * 非空检验
     *
     * @param object  对象
     * @param message 如果为空报的异常信息
     */
    private static void notNull(Object object, String message) {
        if (message == null) {
            message = "No Object specified";
        }
        if (object == null) {
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * @param url
     * @param clazz
     * @param json
     * @param <T>
     * @return
     */
    private static <T> T bodyToModel(String url, Class<T> clazz, String json) {
        if (json == null) {
            return null;
        }
        boolean flag1 = json.startsWith("{") && json.endsWith("}");
        boolean flag2 = json.startsWith("[") && json.endsWith("]");
        if (flag1 || flag2) {
            return JsonUtil.parse(json, clazz);
        } else {
            log.error("地址 {} 返回的数据不是JSON数据", url);
            return null;
        }
    }

    /**
     * 同步get请求
     *
     * @param url    地址
     * @param params 参数
     * @return http访问返回的结果
     */
    public static String get(String url, Map<String, Object> params) {
        OkHttpClient okHttpClient = new OkHttpClient();
        url = url + paramsJoin(params);
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Call call = okHttpClient.newCall(request);
        return getResult(call);
    }

    /**
     * 同步get请求
     *
     * @param url 地址
     * @return http访问返回的结果
     */
    public static String get(String url) {
        return get(url, PARAMS);
    }

    /**
     * 同步get请求
     *
     * @param url    地址
     * @param params 参数
     * @param clazz  反序列化的Class
     * @return http访问返回的如果是JSON数据则直接反序列化成该class的类
     */
    public static <T> T get(String url, Map<String, Object> params, Class<T> clazz) {
        return bodyToModel(url, clazz, get(url, params));
    }

    /**
     * 同步get请求
     *
     * @param url   地址
     * @param clazz 反序列化的Class
     * @return http访问返回的如果是JSON数据则直接反序列化成该class的类
     */
    public static <T> T get(String url, Class<T> clazz) {
        return get(url, PARAMS, clazz);
    }

    /**
     * 异步get请求
     *
     * @param url      地址
     * @param params   参数
     * @param callback Callback回调对象
     */
    public static void get(String url, Map<String, Object> params, Callback callback) {
        notNull(callback, "No Callback specified");
        OkHttpClient okHttpClient = new OkHttpClient();
        url = url + paramsJoin(params);
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
    }

    /**
     * 异步get请求
     *
     * @param url      地址
     * @param callback Callback回调对象
     */
    public static void get(String url, Callback callback) {
        get(url, PARAMS, callback);
    }

    /**
     * 同步post请求
     *
     * @param url    地址
     * @param params 参数
     * @return http访问返回的结果
     */
    public static String post(String url, Map<String, Object> params) {
        OkHttpClient okHttpClient = new OkHttpClient();
        RequestBody requestBody = getRequestBody(params);
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Call call = okHttpClient.newCall(request);
        return getResult(call);
    }

    /**
     * 同步post请求
     *
     * @param url 地址
     * @return http访问返回的结果
     */
    public static String post(String url) {
        return post(url, PARAMS);
    }

    /**
     * 同步post请求
     *
     * @param url    地址
     * @param params 参数
     * @param clazz  反序列化的Class
     * @return http访问返回的如果是JSON数据则直接反序列化成该class的类
     */
    public static <T> T post(String url, Map<String, Object> params, Class<T> clazz) {
        return bodyToModel(url, clazz, post(url, params));
    }

    /**
     * 同步post请求
     *
     * @param url   地址
     * @param clazz 反序列化的Class
     * @return http访问返回的如果是JSON数据则直接反序列化成该class的类
     */
    public static <T> T post(String url, Class<T> clazz) {
        return post(url, PARAMS, clazz);
    }

    /**
     * 异步post请求
     *
     * @param url      地址
     * @param params   参数
     * @param callback Callback回调对象
     */
    public static void post(String url, Map<String, Object> params, Callback callback) {
        OkHttpClient okHttpClient = new OkHttpClient();
        RequestBody requestBody = getRequestBody(params);
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
    }

    /**
     * 异步post请求
     *
     * @param url      地址
     * @param callback Callback回调对象
     */
    public static void post(String url, Callback callback) {
        post(url, PARAMS, callback);
    }

    public static void main(String[] args) {
//        System.out.println();
//        get("http://wwww.baidu.com", new BaseCallback() {
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                ResponseBody body = response.body();
//                byte[] bytes = body != null ? body.bytes() : new byte[0];
//                String json = new String(bytes);
//                System.out.println(json);
//            }
//        });
        Map<String, Object> map = new HashMap<>();
//        map.put("city", "%E5%8C%97%E4%BA%AC");
        map.put("city", "北京");
        map.put("key", "0e62cb04acd415d800720b3e71b3ecd5");
        String url = "http://apis.juhe.cn/simpleWeather/query";
        get(url, map);
        post(url, map, new BaseModelCallback<Map>() {
            @Override
            public void onResponse(Call call, Map model) {
                System.out.println(model);
            }
        });
//        System.out.println(post(url, map, Weather.class));
//        System.out.println(get(url + "?city=%E5%8C%97%E4%BA%AC&key=0e62cb04acd415d800720b3e71b3ecd5", Weather.class));
//        Map<String, Object> m = new HashMap<>();
//        m.put("city", "%E5%8C%97%E4%BA%AC");
//        m.put("key", "0e62cb04acd415d800720b3e71b3ecd5");
//        System.out.println(get("http://apis.juhe.cn/simpleWeather/query", m));
    }

}
